﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Structures
{
    [Serializable]
    public class X3dModel : IComparable
    {
        public Vector3 Scale { get; set; }
        public Vector3 BBoxCenter { get; set; }
        public Vector3 BBoxSize { get; set; }
        public Vector3 Translation { get; set; }
        public Vector4 Rotation { get; set; }
        public Vector4 ScaleOrientation { get; set; }
        public Int16[] Indices { get; private set; }
        public VertexPositionNormalTexture[] Vertices { get; private set; }        
        public Vector3 Center { get; set; }

        [NonSerialized]
        public IndexBuffer ModelIndices;
        [NonSerialized]
        public VertexBuffer ModelData;

        public Bounding bounding { get; private set; }

        public Vector3 ParentTranslation { get; private set; }
        public Matrix World { get; set; }

        
        //public Model bSphereModel { get; set; }
        //public Texture2D sphereTexture { get; set; }

        public bool Touchable { get; set; }

        public X3dModel()
        {
            Translation = Vector3.Zero;
            Center = Vector3.Zero;
            Scale = new Vector3(1, 1, 1);
            Rotation = new Vector4(0, 0, 1, 0);
            ScaleOrientation = new Vector4(0, 0, 1, 0);
            BBoxCenter = Vector3.Zero;
            BBoxSize = new Vector3(-1, -1, -1);
            World = Matrix.Identity;

        }

        public void setModelData(VertexPositionNormalTexture[] vertex, Game game)
        {
            Vertices = vertex;
            BuildVertexBuffer(game.GraphicsDevice);

            var q = Quaternion.CreateFromAxisAngle(new Vector3(Rotation.X, Rotation.Z, Rotation.Y), Rotation.W);
            var sr = Quaternion.CreateFromAxisAngle(new Vector3(ScaleOrientation.X, ScaleOrientation.Z, ScaleOrientation.Y), ScaleOrientation.W);

            var elems = (from v in vertex select Vector3.Transform(v.Position, World)).ToArray();

            bounding = Bounding.CreateFromPoints(elems);
        }

        public void BuildVertexBuffer(GraphicsDevice graphic)
        {
            ModelData = new VertexBuffer(graphic, typeof(VertexPositionNormalTexture), Vertices.Length, BufferUsage.None);
            ModelData.SetData(Vertices);
        }

        public void setModelIndices(GraphicsDevice graphic, Int16[] indices)
        {            
            Indices = indices;
            BuildIndexBuffer(graphic);
        }

        public void BuildIndexBuffer(GraphicsDevice graphic)
        {
            ModelIndices = new IndexBuffer(graphic, IndexElementSize.SixteenBits, Indices.Length, BufferUsage.None);
            ModelIndices.SetData(Indices);
        }

        public void DrawModel(GraphicsDevice graphic, BasicEffect effect)
        {

            effect.World = World;

            graphic.SetVertexBuffer(ModelData);
            graphic.Indices = ModelIndices;
            effect.CurrentTechnique.Passes[0].Apply();
            graphic.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, ModelData.VertexCount, 0, ModelIndices.IndexCount / 3);
            

            //effect.Parameters["World"].SetValue(World);
            ////effect.Begin();
            //effect.CurrentTechnique.Passes[0].Apply();
            //graphic.DrawUserIndexedPrimitives<VertexPositionNormalTexture>(PrimitiveType.TriangleList, Vertices, 0, Vertices.Count(), Indices, 0, Indices.Count());

            ////graphic.Indices = ModelIndices;

            ////graphic.SetVertexBuffer(ModelData);
            ////graphic.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0,ModelData.VertexCount, 0, 3);


            //effect.CurrentTechnique.Passes[0].End();
            //effect.End();
        }
        //public void DrawBSphereModel(ICameraService camera)
        //{
        //    foreach (ModelMesh mesh in bSphereModel.Meshes)
        //    {
        //        foreach (BasicEffect be in mesh.Effects)
        //        {

        //            Matrix world =
        //                 Matrix.CreateScale(bSphere.Radius) *
        //                 Matrix.CreateTranslation(bSphere.Center);
        //            be.Projection = camera.Projection;
        //            be.View = camera.View;
        //            be.World = world;
        //            be.Texture = sphereTexture;
        //            be.TextureEnabled = true;


        //        }
        //        mesh.Draw();
        //    }
        //}


        public int CompareTo(object obj)
        {
            if (Object.ReferenceEquals(this,obj)) return 0;
            else return 1;
        }

        //public void GetObjectData(SerializationInfo info, StreamingContext context)
        //{
            
        //}
    }
}